/* LEDC (LED Controller) fade example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp_err.h"
#include "rotat_ec11_drv.h"

#define EC1X_NUM    (2)
static ec1x_data_t ec1x_data[EC1X_NUM] = {0};

static uint8_t ec1x_1_flag = 0; // 全局标志位
static uint8_t ec1x_1_icnt = 0; // 中断计数变量

static uint8_t ec1x_2_flag = 0; // 全局标志位
static uint8_t ec1x_2_icnt = 0; // 中断计数变量

int rotation_num;

static void send_rotation_msg(KEY_INDEX_e index, ROTATION_event_e event)
{
    MAIN_MSG_t send_msg = {0};

    send_msg.type = ROTATION_TYPE;
    send_msg.data.rota.id = index;
 
    send_msg.data.rota.event = event;
    xQueueSend(my_main_queue, (void*)&send_msg, (TickType_t)0);
}

/*********************************
 * 
 * 	// 计数变量为 0，并且 a 相为低电平
	// 在 if 内部判断 b 相电平，这样就可以确保 a b 两相的电平一高一低了
	// 也就滤出了可能出现的 ab 两相电平同时为高或同时为低的情况
	// 中断计数的作用是只有该判断为真，并且 ec1x_1_icnt 为 1 的情况才进行下一次的判断

    	// 中断计数为 1，并且 a 相为高电平
	// 因为 这是第二次的判断，所以要判断a相为高电平，也就是中断的上升沿
	// 然后就是判断编码器的旋转方向，这里用到了 b 相的状态
	// 通过判断两次 b 相的高低变化就可以判断旋转方向了
 * **/

/* 外部中断服务函数定义 */
static void IRAM_ATTR gpio_isr_handler(void* arg)
{
    //=======第一個旋鈕開關=======
    if (gpio_get_level(ec1x_data[0].a_pin) == 0 && ec1x_1_icnt == 0)
    {
        ec1x_1_flag = 0; // 初始化标志位
        if (gpio_get_level(ec1x_data[0].b_pin)) {
            ec1x_1_flag = 1; // 判断 B相电平为高，为高 ec1x_1_flag 设置为 1
        }
        ec1x_1_icnt = 1; // 中断计数
    }

    if (ec1x_1_icnt && gpio_get_level(ec1x_data[0].a_pin))
    {
		// 判断 b 相为低，并且上次 b 相为高
        if((gpio_get_level(ec1x_data[0].b_pin)) == 0 && ec1x_1_flag == 1) {
            rotation_num = 1;               // 可以在這裡將旋鈕信息發出去
            send_rotation_msg(ROTATION1, ROTA_POSITIVE);
        }
		// 判断 b 相为高，并且上次 b 相为低
        if((gpio_get_level(ec1x_data[0].b_pin)) && ec1x_1_flag == 0){
            rotation_num = -1;              // 可以在這裡將旋鈕信息發出去
            send_rotation_msg(ROTATION1, ROTA_NEGATIVE);
        } 
        ec1x_1_icnt = 0;
    }
    //=====第二個旋鈕開關====
    if (gpio_get_level(ec1x_data[1].a_pin) == 0 && ec1x_2_icnt == 0)
    {
        ec1x_2_flag = 0; // 初始化标志位
        if (gpio_get_level(ec1x_data[1].b_pin)) {
            ec1x_2_flag = 1; // 判断 B相电平为高，为高 ec1x_1_flag 设置为 1
        }
        ec1x_2_icnt = 1; // 中断计数
    }

    if (ec1x_2_icnt && gpio_get_level(ec1x_data[1].a_pin))
    {
		// 判断 b 相为低，并且上次 b 相为高
        if((gpio_get_level(ec1x_data[1].b_pin)) == 0 && ec1x_2_flag == 1) {
            rotation_num = 2;          // 可以在這裡將旋鈕信息發出去
            send_rotation_msg(ROTATION2, ROTA_POSITIVE);
        }
		// 判断 b 相为高，并且上次 b 相为低
        if((gpio_get_level(ec1x_data[1].b_pin)) && ec1x_2_flag == 0){
            rotation_num = -2;         // 可以在這裡將旋鈕信息發出去
             send_rotation_msg(ROTATION2, ROTA_NEGATIVE);
        } 
        ec1x_2_icnt = 0;
    }
}

void rotation_gpio_init(gpio_num_t a_pin, gpio_num_t b_prot)
{

    /* 创建 io 配置变量，并配置 io 中断触发 */
    gpio_config_t io_conf = {};
	// A 相 IO 配置为中断上升沿/下降沿都触发的模式
    io_conf.intr_type = GPIO_INTR_ANYEDGE; /* 上升沿/下降沿都触发 */
    io_conf.mode = GPIO_MODE_INPUT;
    io_conf.pin_bit_mask = 1ULL<<a_pin; // A 相接 D4
    io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
    io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
    gpio_config(&io_conf);

    gpio_install_isr_service(0);
    gpio_isr_handler_add(a_pin, gpio_isr_handler, (void*)0);

	// B 相 IO 配置为普通的输入模式
    io_conf.intr_type = GPIO_INTR_DISABLE; /* 禁用中断 */
    io_conf.mode = GPIO_MODE_INPUT;
    io_conf.pin_bit_mask = 1ULL<<b_prot; // B 相接 D15
    io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
    io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
    gpio_config(&io_conf);

}


/************************************/
// gpio 需要跟据实际板子调整
/************************************/
void rotation_ec11_init(void)
{
    uint8_t i;

    ec1x_data[0].a_pin = GPIO_NUM_6;
    ec1x_data[0].b_pin = GPIO_NUM_10;

    ec1x_data[1].a_pin = GPIO_NUM_0;       
    ec1x_data[1].b_pin = GPIO_NUM_1;
    for(i = 0; i < EC1X_NUM; i++)
    {
        rotation_gpio_init(ec1x_data[i].a_pin, ec1x_data[i].b_pin);
    }
}
